﻿using Basic.Cluster.Manager;
using Consul;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace System
{
    public static class ConsulExtension
    {
        /// <summary>
        /// Consul注册配置
        /// </summary>
        /// <param name="services"></param>
        /// <param name="section"></param>
        /// <returns></returns>
        public static IServiceCollection AddRegisterConsul(this IServiceCollection services, IConfigurationSection section)
        {
            var consulConfig = section.Get<ConsulConfig>();
            ConsulClient consulClient = new ConsulClient(s => { s.Address = new Uri(consulConfig.ConsulAddress); });

            services.AddSingleton(consulConfig);
            services.AddSingleton(consulClient);
            services.AddHealthChecks();

            return services;
        }

        /// <summary>
        /// 启用Consul注册
        /// </summary>
        /// <param name="app"></param>
        /// <returns></returns>
        public static IApplicationBuilder UseRegisterConsul(this IApplicationBuilder app)
        {
            var provider = app.ApplicationServices;

            // 获取主机生命周期对象
            var lifetime = provider.GetRequiredService<IHostApplicationLifetime>();
            var consulClient = provider.GetRequiredService<ConsulClient>();
            var confInfo = provider.GetRequiredService<ConsulConfig>();
            string healthAddress = $"http://{confInfo.LocalServiceInfo.IP}:{confInfo.LocalServiceInfo.Port}{confInfo.LocalServiceInfo.HealthUrl}";

            app.UseHealthChecks(confInfo.LocalServiceInfo.HealthUrl);

            var check = new AgentServiceCheck
            {
                CheckID = confInfo.LocalServiceInfo.Id,
                HTTP = healthAddress,
                Interval = TimeSpan.FromSeconds(confInfo.HealthInterval ?? 15),
                Timeout = TimeSpan.FromSeconds(confInfo.HealthInterval ?? 5),
                DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(2),
            };
            var registration = new AgentServiceRegistration()
            {
                Check = check,
                ID = confInfo.LocalServiceInfo.Id,
                Name = confInfo.LocalServiceInfo.Name,
                Address = confInfo.LocalServiceInfo.IP,
                Port = confInfo.LocalServiceInfo.Port,
            };

            lifetime.ApplicationStarted.Register(async () =>
            {
                _ = await consulClient.Agent.ServiceRegister(registration);
            });

            lifetime.ApplicationStopping.Register(async () =>
            {
                _ = await consulClient.Agent.ServiceDeregister(registration.ID);
            });
            return app;
        }


    }
}